Csrf.php

<?php

namespace Tlf\User\Test\Gui;

class Csrf extends \Tlf\User\GuiTester {

    public function testSubmitResetWithCsrfCheck(){
        //////
        // get session id
        //////
        $response = $this->curl_get('/user/reset-password/', ['enable_csrf'=>true]);
        $content = $response['body'];
        $session_id = $response['cookies']['PHPSESSID']['value'];
        // $csrf = json_decode($content, true);

        // get the csrf key & code
        $doc = new \Taeluf\PHTML($response['body']);
        $node = $doc->xpath('//input[@type="hidden"]', $refNode=null)[0];
        $csrf_key = $node->name;
        $csrf_code = $node->value;

        //////
        // test the POST
        //////
        $lib = new \Tlf\User\Lib($this->pdo());
        $email = 'reed@reset.password.csrf';
        $user = $this->get_active_user($email, 'abc');

        $response = $this->curl_post('/user/reset-password/', 
            [
                'email'=>$email,
                'test_spoof_ip'=>'reqpasschange.csrf',
                $csrf_key=>$csrf_code,
                'enable_csrf'=>true,
                'logs_consent'=>'on',
            ],
            $files=[],'backward_compat',
            [
               'REFERER: '.$this->cli->get_server_host(),
               'Cookie'=> 'PHPSESSID='.$session_id,
            ]
        );

        $response = $response['body'];
        // echo $response;
        // exit;

        $this->test("Response");
        $msg = sprintf('An email has been sent to %s. Please check your email to finish resetting your password', $email);
        $this->str_contains($response,$msg);

        $this->str_not_contains($response,'<form');


        $this->test("Email message");
        $msg = $this->get_email();
        $user = $lib->user_from_email($email);
        $ldb = new \Tlf\LilDb($this->pdo());
        $code_rows = $ldb->select('code',['user_id'=>$user->id, 'type'=>'password_reset']);
        $reset_code = $code_rows[0]['code'];
        $target_url = 'http://create.localhost/user/complete.password_reset.'.$reset_code.'/';
        $target_msg = "To setup a new password, visit <a href=\"$target_url\">$target_url</a>.";
        $this->compare($target_msg,$msg);

        // i will likely later write a test that is the entire flow


//
        // $login_code = $user->password_login('abc');
        // $this->is_string($login_code);
//
        // $complete_reset_form = $this->get('/complete.password_reset.'.$reset_code.'/');
//
//
        // $this->is_false($user->password_login('abc'));
    }

    public function testCsrfSpoofNoPost(){
        $bad_response = $this->post('/csrf-test-post/', [],
        );
        echo $bad_response;

        $this->str_contains(
            $bad_response,
            'csrf post test success' 
        );

    }
    public function testCsrfSpoof(){
        $bad_response = $this->post('/csrf-test-post/', ['csrf-test-csrf-random_code'=>'fake_code'],
        );

        $this->str_contains(
            $bad_response,
            'csrf post test success' 
        );

    }

    public function testValidateCsrf(){
        $response = $this->curl_post('/csrf-test/', ['enable_csrf'=>true]);
        $content = $response['body'];
        $session_id = $response['cookies']['PHPSESSID']['value'];
        $csrf = json_decode($content, true);

        $bad_response = $this->curl_post('/csrf-test-post/', [$csrf['key']=>null, 'enable_csrf'=>true],
            $files=[],'backward_compat',
            [
               'REFERER: '.$this->cli->get_server_host(),
               'Cookie'=> 'PHPSESSID='.$session_id,
            ]
        );

        $this->str_contains(
            $bad_response['body'],
            'csrf post test not valid'
        );
        echo "\n\nInvalid Response:\n".$bad_response['body'];

        $good_response = $this->curl_post('/csrf-test-post/', [$csrf['key']=>$csrf['code'], 'enable_csrf'=>true],
            $files=[],'backward_compat',
            [
               'REFERER: '.$this->cli->get_server_host(),
               'Cookie'=> 'PHPSESSID='.$session_id,
            ]
        );

        $this->str_contains($good_response['body'],
            'csrf post test success'
        );

        echo "\n\nGood Response:\n".$good_response['body'];
    }

    public function testGenCsrf(){
        $content = $this->get('/csrf-test/', ['enable_csrf'=>true]);
        $csrf = json_decode($content, true);

        $this->is_string($csrf['code']);
        $this->is_true($csrf['expires_at'] > time());
        $this->is_true($csrf['expires_at'] < time() + 60 * 10 + 1);
        $this->compare($csrf['uri'], '/csrf-test-post/');

    }
}